home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
program
/
recio215.zip
/
RECIO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-26
|
15KB
|
409 lines
/*****************************************************************************
MODULE: recio.c
PURPOSE: record input/output functions
COPYRIGHT: (C) 1994-1996, William Pierpoint
COMPILER: Borland C Version 3.1
OS: MSDOS Version 6.2
VERSION: 2.15
RELEASE: October 26, 1996
*****************************************************************************/
#include <ctype.h>
#include <errno.h>
#include <float.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "recio.h"
#define rcol(rp) ((rp)->r_colno)
#define rflags(rp) ((rp)->r_flags)
#define rfd(rp) ((rp)->r_fd)
#define rfp(rp) ((rp)->r_fp)
#define rreclen(rp) ((rp)->r_reclen)
#define rrecsiz(rp) ((rp)->r_recsiz)
#define rfldsiz(rp) ((rp)->r_fldsiz)
#define rfldch(rp) ((rp)->r_fldch)
#define rtxtch(rp) ((rp)->r_txtch)
#define rtmfmt(rp) ((rp)->r_tmfmt)
/* private module variables */
static REC *_RECS = NULL; /* ptr to array of RECs */
static char _tmfmt[] = "%m/%d/%y"; /* default time format string */
static REC rin = { 1, 0, stdin, "stdin", 0L,
0, 0, 0, 0, NULL,
0, NULL, RECFLDCH, RECTXTCH, _tmfmt, RECIN };
static REC rout = { 2, _R_WRT, stdout, "stdout", 0L,
0, 0, 0, 0, NULL,
0, NULL, RECFLDCH, RECTXTCH, _tmfmt, RECOUT };
static REC rerr = { 3, _R_WRT, stderr, "stderr", 0L,
0, 0, 0, 0, NULL,
0, NULL, RECFLDCH, RECTXTCH, _tmfmt, RECERR };
#if (R_NREC >= 4)
static REC rprn = { 4, _R_WRT, stdprn, "stdprn", 0L,
0, 0, 0, 0, NULL,
0, NULL, RECFLDCH, RECTXTCH, _tmfmt, RECPRN };
#endif
#define ROPEN_MIN R_NREC /* reserved for recin, etc */
#define ROPEN max(ROPEN_MAX, ROPEN_MIN)
/* public variables */
REC *recin = &rin;
REC *recout = &rout;
REC *recerr = &rerr;
#if (R_NREC >= 4)
REC *recprn = &rprn;
#endif
/* friend variables */
char _r_nsbuf[NSBUFSIZ]; /* buffer for numeric to string conversions */
void (*_r_errfn)(REC *); /* pointer to error message function */
/* Support functions */
/****************************************************************************/
static void /* returns nothing */
_rexit( /* at program exit, clean up */
void) /* no arguments */
/****************************************************************************/
{
/* free recin buffers */
free(rflds(recin));
free(rrecs(recin));
rflds(recin) = NULL;
rfldsiz(recin) = 0;
rrecs(recin) = NULL;
rrecsiz(recin) = 0;
rreclen(recin) = 0;
/* ensure all record streams closed */
rcloseall();
}
/****************************************************************************/
void /* return error number (0=no error) */
_rsetexitfn( /* register _rexit function with atexit() */
REC *rp) /* record pointer */
/****************************************************************************/
{
static int once=0; /* register exit fn only once */
if (!once) {
/* execute this path at most one time */
once++;
/* if atexit() fails to register _rexit() function */
if (atexit(_rexit)) {
/* register warning */
rsetwarn(rp, R_WNOREG);
}
}
}
/****************************************************************************/
int /* return error number (0=no error) */
_rmoderror( /* check for mode error */
REC *rp, /* record pointer */
int mode) /* mode (0=read; !0=write/append) */
/****************************************************************************/
{
int errnum=0; /* error number (0=mode ok, !0=invalid mode) */
unsigned smode; /* stream mode */
/* if stream _R_WRT flag does not match mode */
smode = rflags(rp) & _R_WRT;
if ((mode && !smode) || (!mode && smode)) {
errnum = rseterr(rp, R_EINVMOD);
}
return errnum;
}
/****************************************************************************/
int /* return !0 if ready; 0 if in error state */
_risready( /* see if record stream is ready */
REC *rp, /* record pointer */
int mode) /* mode (0=read; !0=write/append) */
/****************************************************************************/
{
int errnum=0; /* error number */
/* test for valid record pointer */
if (!risvalid(rp)) {
errnum = rseterr(NULL, EINVAL);
goto done;
}
/* check mode */
errnum = _rmoderror(rp, mode);
if (errnum) goto done;
/* if record 0 and write mode, set record number to 1 */
if (!rrecno(rp) && mode) rrecno(rp)++;
/* test for any previous error */
errnum = rerror(rp);
done:
return (!(errnum));
}
/****************************************************************************/
static void /* returns nothing */
_rfree( /* free the memory allocated to a record */
REC *rp) /* record pointer */
/****************************************************************************/
{
if (risvalid(rp)) {
free(rflds(rp));
free(rrecs(rp));
if (rfp(rp)) fclose(rfp(rp));
memset(rp, 0, sizeof(REC));
}
}
/* User functions */
/****************************************************************************/
REC * /* return record pointer */
ropen( /* open a record stream for reading */
const char *fname, /* name of file to open */
const char *mode) /* type of mode used to open file */
/****************************************************************************/
{
REC *rp = _RECS; /* record pointer */
int i; /* count of REC structures */
int ch; /* first character of mode */
errno = 0;
/* only modes currently supported are "r", "w", and "a" */
ch = tolower(*mode);
if (!(ch=='r' || ch=='w' || ch=='a')) {
rp = NULL;
rseterr(NULL, EINVAL);
goto done;
}
/* allocate memory for array of REC structures */
if (!rp) {
do {
/* note: no memory allocation needed for recin, etc */
rp = _RECS = (REC *) calloc(ROPEN-R_NREC, sizeof(REC));
if (!rp) {
if (rseterr(NULL, ENOMEM)) goto done;
}
} while (!rp);
}
/* search thru REC structures until empty position found */
for (i=R_NREC+1; i <= ROPEN; i++, rp++) {
if (!rfd(rp)) {
rfd(rp) = i;
break;
}
}
/* error if out of positions */
if (i > ROPEN) {
rp = NULL;
rseterr(NULL, EMFILE);
goto done;
}
/* open file */
rfp(rp) = fopen(fname, mode);
if (!rfp(rp)) {
rclose(rp);
rp = NULL;
/* if error other than path/file not found */
if (errno != ENOENT) {
rseterr(NULL, errno);
}
goto done;
}
/* initialize */
rflags(rp) = 0;
if (ch != 'r') rflags(rp) |= _R_WRT;
rnames(rp) = fname;
rrecno(rp) = 0L;
rfldno(rp) = 0;
rcol(rp) = 0;
rrecsiz(rp) = 0;
rreclen(rp) = 0;
rrecs(rp) = NULL;
rfldsiz(rp) = 0;
rflds(rp) = NULL;
rfldch(rp) = RECFLDCH;
rtxtch(rp) = RECTXTCH;
rtmfmt(rp) = _tmfmt;
rcxtno(rp) = 0;
_rsetexitfn(rp);
done:
return rp;
}
/****************************************************************************/
void /* returns nothing */
rclose( /* close a record stream */
REC *rp) /* record pointer */
/****************************************************************************/
{
int i; /* count REC structures */
REC *recp=_RECS; /* pointer to _RECS array */
if (risvalid(rp)) {
/* close record stream, but not recin, recout, recerr */
if (rfd(rp) > R_NREC) _rfree(rp);
/* if all record streams closed, free _RECS */
/* note: valid rp implies valid recp */
for (i=R_NREC+1; i <= ROPEN; i++, recp++) {
if (rfd(recp)) goto done;
}
free(_RECS);
_RECS = NULL;
} else {
rseterr(NULL, EINVAL);
}
done:
return;
}
/****************************************************************************/
int /* returns number of streams closed */
rcloseall( /* close all record streams */
void) /* no arguments */
/****************************************************************************/
{
int num=0; /* number of streams closed */
int i; /* count REC structures */
REC *recp=_RECS; /* pointer to _RECS array */
/* close every open record stream, except recin, etc */
if (recp) {
for (i=R_NREC+1; i <= ROPEN; i++, recp++) {
if (rfd(recp)) {
_rfree(recp);
num++;
}
}
free(_RECS);
_RECS = NULL;
}
return num;
}
/****************************************************************************/
int /* return !0 for valid; 0 for invalid */
risvalid( /* is record pointer valid? */
REC *rp) /* record pointer */
/****************************************************************************/
{
int valid=1; /* validation state (!0=valid) */
/* if rp is null pointer or rfd not between 1 and ROPEN */
if (!rp || rfd(rp) < 1 || rfd(rp) > ROPEN) {
/* invalid record pointer */
valid = 0;
}
return valid;
}
/****************************************************************************/
void /* returns nothing */
rsetfldch( /* set field separator character */
REC *rp, /* record pointer */
int ch) /* field separator character */
/****************************************************************************/
{
if (risvalid(rp)) {
if (isascii(ch)) {
rfldch(rp) = ch;
} else {
rseterr(rp, R_EINVAL);
}
} else {
rseterr(NULL, EINVAL);
}
}
/****************************************************************************/
void /* returns nothing */
rsettxtch( /* set text string delimiter character */
REC *rp, /* record pointer */
int ch) /* text delimiter character */
/****************************************************************************/
{
if (risvalid(rp)) {
if (isascii(ch)) {
rtxtch(rp) = ch;
} else {
rseterr(rp, R_EINVAL);
}
} else {
rseterr(NULL, EINVAL);
}
}
/****************************************************************************/
void /* returns nothing */
rsettmfmt( /* set time format string for record stream */
REC *rp, /* record pointer */
const char *fmt) /* time format string */
/****************************************************************************/
{
if (risvalid(rp)) {
rtmfmt(rp) = fmt;
} else {
rseterr(NULL, EINVAL);
}
}
/****************************************************************************/
void /* returns nothing */
rsetcxtno( /* set context number of record stream */
REC *rp, /* record pointer */
int cxtno) /* context number */
/****************************************************************************/
{
if (risvalid(rp)) {
if (rcxtno(rp) >= 0 && cxtno >= 0) {
rcxtno(rp) = cxtno;
} else {
rseterr(rp, R_EINVAL);
}
} else {
rseterr(NULL, EINVAL);
}
}
/****************************************************************************/
void /* returns nothing */
rsetbegcolno( /* set beginning record column number */
REC *rp, /* record pointer */
int colno) /* first column in record is 0 or 1 */
/****************************************************************************/
{
if (risvalid(rp)) {
if (colno == 1) {
rflags(rp) |= _R_COL;
} else if (colno == 0) {
rflags(rp) &= ~_R_COL;
} else {
rseterr(rp, R_EINVAL);
}
} else {
rseterr(NULL, EINVAL);
}
}